/**
 * 使一个元素可以被拖动
 */
(function(){
    Simple.mixin(Simple, {
        getRealPos: function(element){
            var position = element.css("position"), top, left, parentOffset, offset = element.offset(), right, bottom;
            if (position == "static") {
                element.css("position", "relative");
                top = 0;
                left = 0;
            }
            else 
                if (position == "absolute") {
                    var parent = element.parent()
                    while (parent.css("position") == "static" && !parent.is("body")) {
                        parent = parent.parent();
                    }
                    parentOffset = parent.offset();
                    top = offset.top - parentOffset.top;
                    left = offset.left - parentOffset.left;
                }
                else 
                    if (position == "fixed") {
                        top = parseFloat(element.css("top"));
                        left = parseFloat(element.css("left"));
                        if (isNaN(top)) {
                            top = offset.top - Math.max(document.documentElement.scrollTop, document.body.scrollTop);
                        }
                        if (isNaN(left)) {
                            left = offset.left;
                        }
                    }
                    else 
                        if (position == "relative") {
                            top = parseFloat(element.css("top"));
                            left = parseFloat(element.css("left"));
                            right = parseFloat(element.css("right"));
                            bottom = parseFloat(element.css("bottom"));
                            if (isNaN(top)) {
                                if (!isNaN(bottom)) {
                                    top = -bottom
                                }
                                else {
                                    top = 0;
                                }
                            }
                            if (isNaN(left)) {
                                if (!isNaN(right)) {
                                    left = -right
                                }
                                else {
                                    left = 0;
                                }
                            }
                        }
            return {
                left: left,
                top: top
            }
        },
        getCoordinates: function(element){
            var coor = {};
            element = $(element);
            if (element.length < 1) {
                return;
            }
            var offset = element.offset(), right = element.outerWidth() + offset.left, bottom = element.outerHeight() + offset.top;
            Simple.mixin(coor, {
                right: right,
                bottom: bottom
            }, offset);
            return coor;
        },
        getWinScroll: function(){
            return {
                x: Math.max(document.documentElement.scrollLeft, document.body.scrollLeft),
                y: Math.max(document.documentElement.scrollTop, document.body.scrollTop)
            }
        }
    })
    //防止选中文字
    $.fn.noSelect = function(p){
        var prevent = (p == null) ? true : p;
        if (prevent) {
            return this.each(function(){
                if ($.browser.msie || $.browser.safari) 
                    $(this).bind('selectstart', function(){
                        return false;
                    });
                else 
                    if ($.browser.mozilla) {
                        $(this).css('MozUserSelect', 'none');
                        $('body').trigger('focus');
                    }
                    else 
                        if ($.browser.opera) 
                            $(this).bind('mousedown', function(){
                                return false;
                            });
                        else 
                            $(this).attr('unselectable', 'on');
            });
        }
        else {
            return this.each(function(){
                if ($.browser.msie || $.browser.safari) 
                    $(this).unbind('selectstart');
                else 
                    if ($.browser.mozilla) 
                        $(this).css('MozUserSelect', 'inherit');
                    else 
                        if ($.browser.opera) 
                            $(this).unbind('mousedown');
                        else 
                            $(this).removeAttr('unselectable', 'on');
            });
        }
    };
    Simple.declare("Drag", null, {
        node: null,
        handle: null,
        container: null,
        proxy: null,
        delay: 2,
        atCursor: null,
        iframeFix: false,
        direction: "both",
        grid: false,
        revert: false,
        ondragstart: $.noop,
        ondrag: $.noop,
        ondragstop: $.noop,
        dropElements: false,
        ondragenter: $.noop,
        ondragleave: $.noop,
        ondragdrop: $.noop,
        init: function(){
            var self = this;
            if (this.handle) {
                this.handle = $(this.node).find(this.handle);
            }
            else {
                this.handle = $(this.node);
            }
            if (this.dropElements) {
                this.dropElements = $(this.dropElements);
            }
            this.handle.bind("drag/draggable", function(e, event){
                self._movestart.apply(self, [event]);
            })
            this.handle.mousedown(function(e){
                if ($(e.target).is("input")) {
                    return;
                }
                self.handle.trigger("drag/draggable", [e]);
                return false;
            });
        },
        destroy: function(){
            this.handle.unbind("drag/draggable");
        },
        _movestart: function(e){
            e.stopPropagation();
            var s = this, node = $(s.node);
            s.lastX = e.pageX;
            s.lastY = e.pageY;
            s.lastNodeX = Simple.getRealPos(node).left;
            s.lastNodeY = Simple.getRealPos(node).top;
            s.offset = node.offset();
            s.nodeWidth = node.outerWidth();
            s.nodeHeight = node.outerHeight();
            if (typeof s.ondragstart == "function") {
                s.ondragstart.apply(s.node, [e, s]);
            }
            $(document).mousemove(function(e){
                s._moving.apply(s, [e]);
                return false;
            });
            $(document).mouseup(function(e){
                s._movestop.apply(s, [e]);
                return false;
            });
            s._setContainer();
            s._setIframeFix();
            node.hasClass("draggable") && node.addClass("draggable");
            this.overed = null;
            $(document.body).noSelect();
        },
        _moving: function(e){
            var s = this, node = $(this.node), needSetElement;
            s.moveX = e.pageX;
            s.moveY = e.pageY;
            s.changeX = s.moveX - s.lastX;
            s.changeY = s.moveY - s.lastY;
            //延迟拖动
            if (Math.abs(s.changeX) > s.delay && Math.abs(s.changeY) > s.delay) {
				this.hasDrag=true;
                $(document.body).css("cursor", "move");
                $(".draggable-iframeFix").show();
                //网格拖动
                if (this.grid) {
                    this.changeY = Math.round(this.changeY / this.grid[1]) * this.grid[1]
                    this.changeX = Math.round(this.changeX / this.grid[0]) * this.grid[0]
                }
                //拖动区域
                if (s.dragRegion) {
                    if (s.offset.left + s.changeX < s.dragRegion.left) {
                        s.changeX = s.dragRegion.left - s.offset.left
                    }
                    if (s.offset.left + s.changeX + s.nodeWidth > s.dragRegion.right) {
                        s.changeX = s.dragRegion.right - s.offset.left - this.nodeWidth
                    }
                    if (s.offset.top + s.changeY < s.dragRegion.top) {
                        s.changeY = s.dragRegion.top - s.offset.top
                    }
                    if (s.offset.top + s.changeY + s.nodeHeight > s.dragRegion.bottom) {
                        s.changeY = s.dragRegion.bottom - s.offset.top - s.nodeHeight
                    }
                }
                s.left = s.lastNodeX + s.changeX;
                s.top = s.lastNodeY + s.changeY;
                
                if (s.proxy) {
                    s._setProxy();
                    needSetElement = s.proxyElement;
                    s._updatePosition(needSetElement, true);
                }
                else {
                    needSetElement = node;
                    s._updatePosition(needSetElement);
                }
                if (typeof s.ondrag == "function") {
                    s.ondrag.apply(node, [e, s]);
                }
                //检测放置
                this.dropElements && this.checkDroppables();
            }
        },
        _movestop: function(e){
                var s = this, needSetElement;
				if(this.hasDrag){
					this.dropElements && this.checkDroppables(true);
				}
                if (s.proxy) {
                    if (!s.revert) {
                        s._updatePosition($(s.node));
                    }
                    needSetElement = s.proxyElement;
                }
                else {
                    needSetElement = s.node;
                }
                //如果要返回原位
                if (s.revert) {
                    $(s.node).animate({
                        left: s.lastNodeX,
                        top: s.lastNodeY
                    });
                }
                //触发拖动停止事件
                if (typeof s.ondragstop == "function") {
                    s.ondragstop.apply(s.node, [e, s]);
                }
                //解除事件绑定
                $(document).unbind("mousemove").unbind("mouseup");
				this.hasDrag=false;
                //移除标识类
                $(this.node).removeClass('draggable');
                $(document.body).css({
                    "cursor": "default"
                }).noSelect(false);
                $(".draggable-iframeFix").hide();
                if (s.proxyElement) {
                    s.proxyElement.remove();
                    s.proxyElement = null;
                }
        },
        //设置拖动的范围
        _setContainer: function(){
            var region = {};
            if (this.container) {
                if (this.container == document.body) {
                    var DOC = document.documentElement;
                    region.left = 0;
                    region.top = 0;
                    region.right = Math.max(DOC.clientWidth, DOC.scrollWidth);
                    region.bottom = Math.max(DOC.clientHeight, DOC.scrollHeight);
                }
                else {
                    var container = $(this.container);
                    region = Simple.getCoordinates(container);
                }
            }
            else {
                region = null;
            }
            this.dragRegion = region;
        },
        //设置代理
        _setProxy: function(){
            if (this.proxyElement) {
                return;
            }
            var proxy = this.proxy, s = this;
            if (typeof proxy == "string") {
                this.proxyElement = $(this.node).clone().css({
                    "position": "absolute",
                    top: s.lastNodeY,
                    left: s.lastNodeX
                });
            }
            else 
                if (typeof proxy == "function") {
                    this.proxyElement = this.proxy.call(this.node);
                    this.proxyElement.css("position", "absolute");
                }
            this.proxyElement.appendTo(document.body);
        },
        //设置鼠标粘滞 FOR IE
        _setCapture: function(e){
        
        },
        _updatePosition: function(needSetEl, proxy){
            var top = this.top, left = this.left;
            if (proxy) {
                top = this.offset.top + this.changeY;
                left = this.offset.left + this.changeX;
                if (this.atCursor) {
                    top = this.moveY + this.atCursor.top;
                    left = this.moveX + this.atCursor.left;
                }
            }
            if (this.direction == "both") {
                needSetEl.css({
                    top: top,
                    left: left
                });
            }
            else 
                if (this.direction == "x") {
                    needSetEl.css({
                        left: left
                    });
                }
                else {
                    needSetEl.css({
                        top: top
                    });
                }
        },
        _setIframeFix: function(){
            if (this.iframeFix) {
                if (!($(".draggable-iframeFix").is("div"))) {
                    var iframeFixDiv = $("<div/>").css({
                        width: "100%",
                        height: "100%",
                        position: "absolute",
                        opacity: 0,
                        zIndex: 10000,
                        top: 0,
                        left: 0
                    }).addClass("draggable-iframeFix");
                    $(document.body).append(iframeFixDiv);
                }
            }
        },
        checkDroppables: function(isDrop){
            var that = this, overed = this.dropElements.filter(function(i, el){
                el = $(el)
                if (that.proxy) {
                    return that.isInteract(el, that.proxyElement)
                }
                else {
                    return that.isInteract(el, that.node);
                }
            }).last();
            if (this.overed != overed[0]) {
                if (this.overed) {
                    this.ondragleave.apply(this.node, [$(this.overed), this]);
                }
                if (overed[0]) {
                    this.ondragenter.apply(this.node, [overed, this]);
                }
                this.overed = overed[0];
            }
            else {
                if (overed[0]) {
                    if (isDrop) {
                        this.ondragdrop.apply(this.node, [overed, this]);
                    }
                }
            }
        },
        getDroppableCoordinates: function(element){
            if (element) {
                var position = Simple.getCoordinates(element);
                if (element.css("position") == "fixed") {
                    var scroll = Simple.getWinScroll();
                    position.top += scroll.y;
                    position.bottom += scroll.y;
                    position.left += scroll.x;
                    position.right += scroll.x;
                }
                return position;
            }
        },
        isInteract: function(nodeA, nodeB){
            var a = this.getDroppableCoordinates(nodeA), b = this.getDroppableCoordinates(nodeB);
            //不相交的情况
            //A top> B bottom
            //A bottom < B top
            //A right < B left
            //A left >B right
            if (a.top > b.bottom || a.bottom < b.top || a.right < b.left || a.left > b.right) {
                return false;
            }
            else {
                return true;
            }
        }
    });
    Simple.bridgeTojQuery("draggable,drag", Simple.Drag);
})();
